﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using BestHTTP;
using System.IO;
using System;

public class DownloadManager : Singleton<DownloadManager> {

    private Queue<DownloadTask> downloadTopTasks = new Queue<DownloadTask>();
    private Queue<DownloadTask> downloadTasks = new Queue<DownloadTask>();

    private const int MaxTopDownloadCount = 1;
    private const int MaxDownloadCount = 1;

    private int currentTopDownloadCount = 0;
    private int currentDownloadCount = 0;

	public override void Init ()
	{
		base.Init ();
        this.downloadTopTasks.Clear();
        this.downloadTasks.Clear ();
        this.currentTopDownloadCount = 0;
        this.currentDownloadCount = 0;
	}

	public void AddTask(DownloadTask task, bool isTopTask = false)
    {
        if (isTopTask)
        {
            this.downloadTopTasks.Enqueue(task);
        }
        else
        {
            this.downloadTasks.Enqueue(task);
        }
	}

	public void Update() {

        if (currentTopDownloadCount < MaxTopDownloadCount && downloadTopTasks.Count > 0)
        {
            this.currentTopDownloadCount++;
            StartDownload(this.downloadTopTasks.Dequeue(), true);
        }

        if (currentDownloadCount < MaxDownloadCount && downloadTasks.Count > 0) {
			this.currentDownloadCount++;
			StartDownload (this.downloadTasks.Dequeue (), false);
		}
	}

	private void StartDownload(DownloadTask task, bool isTopTask) {

        Debug.Log("-------------  开始HTTP请求！ task url: " + task.URL);
		HTTPRequest request = new HTTPRequest(new System.Uri(task.URL), (req, resp) => {
            if (resp.IsSuccess)
            {
                if (req != null)
                {
                    if (resp.IsSuccess)
                    {
                        if (req.State == HTTPRequestStates.Processing || req.State == HTTPRequestStates.Finished)
                        {
                            string fileOnly = task.SavePath.Split(',')[0];
                            string tmpFile = fileOnly + ".empty";
                            List<byte[]> fragments = resp.GetStreamedFragments();
                            if (fragments != null)
                            {
                                using (FileStream fs = new FileStream(tmpFile, FileMode.Append))
                                    foreach (byte[] data in fragments)
                                        fs.Write(data, 0, data.Length);
                            }
                            if (resp.IsStreamingFinished)
                            {
                                FileTools.CopyFile(tmpFile,task.SavePath);
                                FileTools.DeleteFile(tmpFile);
                                if (isTopTask)
                                {
                                    this.currentTopDownloadCount--;
                                }
                                else
                                {
                                    this.currentDownloadCount--;
                                }
                                task.Success();
                            }
                        }
                        else if (req.State == HTTPRequestStates.TimedOut || req.State == HTTPRequestStates.Error || req.State == HTTPRequestStates.ConnectionTimedOut || req.State == HTTPRequestStates.Aborted)
                        {
                            DownloadError(task, isTopTask, req.State.ToString());
                        }
                    }
                    else
                    {
                        Debug.Log("http code:" + resp.StatusCode);
                        DownloadError(task, isTopTask);
                    }
                }
                else
                {
                    DownloadError(task, isTopTask);
                }
            }
            else
                DownloadError(task, isTopTask);

		});
		request.UseStreaming = true;
		request.OnProgress = new OnDownloadProgressDelegate (delegate(HTTPRequest originalRequest, long downloaded, long downloadLength) {
			task.Progress(downloadLength, downloaded);
		});
		request.StreamFragmentSize = 1024 * 1024;
		request.DisableCache = true;
        request.Timeout = TimeSpan.FromSeconds(20);
		request.Send ();
	}

	private void DownloadError(DownloadTask task, bool isTopTask, string error = "unkown error!") {

        if (isTopTask)
        {
            this.currentTopDownloadCount--;
            if (this.currentTopDownloadCount < 0)
            {
                this.currentTopDownloadCount = 0;
            }
        }
        else
        {
            this.currentDownloadCount--;
            if (this.currentDownloadCount < 0)
            {
                this.currentDownloadCount = 0;
            }
        }

		task.Error (error);
	}
}
